//
//  XKScanQRViewController.m
//  xk100
//
//  Created by xiaokang on 2017/6/30.
//  Copyright © 2017年 xiaokang. All rights reserved.
//

#import <AVFoundation/AVFoundation.h>
#import "XKScanQRViewController.h"
#import "XKQRCoderController.h"

@interface XKScanQRViewController ()<AVCaptureMetadataOutputObjectsDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
//捕获设备，通常是前置摄像头，后置摄像头，麦克风（音频输入）
@property(nonatomic)AVCaptureDevice *device;

//AVCaptureDeviceInput 代表输入设备，他使用AVCaptureDevice 来初始化
@property(nonatomic)AVCaptureDeviceInput *input;

//设置输出类型为Metadata，因为这种输出类型中可以设置扫描的类型，譬如二维码
//当启动摄像头开始捕获输入时，如果输入中包含二维码，就会产生输出
@property(nonatomic)AVCaptureMetadataOutput *output;

//session：由他把输入输出结合在一起，并开始启动捕获设备（摄像头）
@property(nonatomic)AVCaptureSession *session;

//图像预览层，实时显示捕获的图像
@property(nonatomic)AVCaptureVideoPreviewLayer *previewLayer;


/** 图片探测器 */
@property(nonatomic, strong)CIDetector *detector;


/** 中间扫描图片 */
@property(nonatomic, strong)UIImageView *imageScanZone;
/** 移动的图片 */
@property(nonatomic, strong)UIImageView *imageMove;
/** 遮罩视图 */
@property(nonatomic, strong)UIView *viewMask;
/** 开启闪光灯 */
@property(nonatomic, strong)UIButton *buttonTurn;
/** 我的二维码 */
@property(nonatomic, strong)UIButton *buttonQRCode;
/** 相册 */
@property(nonatomic, strong)UIButton *buttonAlbum;
/** 提示语 */
@property(nonatomic, strong)UILabel *labelAlert;

/** 开始扫描动画 */
- (void)startAnimation;

/** 关闭扫描动画 */
- (void)stopAnimation;

@property (nonatomic, strong) NSTimer *timer;

@end

@implementation XKScanQRViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.navigationItem.title = @"扫一扫";
    [self creatCaptureDevice];
    
//    // 2.设置UIBarButtonItem， iOS8系统之后才支持本地扫描
//    UIBarButtonItem * rightItem = [[UIBarButtonItem alloc]initWithTitle:@"相册" style:UIBarButtonItemStyleDone target:self action:@selector(alumbEvent)];
//    self.navigationItem.rightBarButtonItem = rightItem;
    
    // 3.添加进入前后台的事件监控
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self authorizationStatus];
    
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self stopAnimation];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
}

// 3.进入前台，重新刷新扫描
- (void)willEnterForeground {
    [self.session stopRunning];
    [self stopAnimation];
    [self performSelector:@selector(authorizationStatus) withObject:self afterDelay:0.1];
}

#pragma mark - 相册
// 3.相册事件
- (void)alumbEvent {
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //判断设备是否支持相册
        [SVProgressHUD showInfoWithStatus:@"未开启访问相册权限"];
        return;
    }
    
    UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
    imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    imagePickerController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
    imagePickerController.allowsEditing = YES;
    imagePickerController.delegate = self;
    [self presentViewController:imagePickerController animated:YES completion:^{
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
    }];
}

#pragma mark - --- UIImagePickerController Delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 1.获取图片信息
    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
    if (!image){
        image = [info objectForKey:UIImagePickerControllerOriginalImage];
    }
    
    // 2.退出图片控制器
    [picker dismissViewControllerAnimated:YES completion:^{
        
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
        
        NSArray *features = [self.detector featuresInImage:[CIImage imageWithCGImage:image.CGImage]];
        if (features.count) { // 1.识别到二维码

            // 1.播放提示音
            [self playSystemSound];
            // 2.显示扫描结果信息
            CIQRCodeFeature *feature = [features objectAtIndex:0];
    
            if ([self.delegate respondsToSelector:@selector(qrCodeScanSuccessWithResult:)]) {
                [self.delegate qrCodeScanSuccessWithResult:feature.messageString];
                [self.navigationController popViewControllerAnimated:NO];
            }
        }else {
            
            if ([self.delegate respondsToSelector:@selector(qrCodeScanSuccessWithResult:)]) {
                [self.delegate qrCodeScanSuccessWithResult:@"没有识别到二维码信息!"];
                [self.navigationController popViewControllerAnimated:NO];
            }
        }
    }];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [picker dismissViewControllerAnimated:YES completion:^{
        [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
    }];
}





- (void)creatCaptureDevice{
    //使用AVMediaTypeVideo 指明self.device代表视频，默认使用后置摄像头进行初始化
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    NSError *error = nil;
    //使用设备初始化输入
    self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:&error];
    
    if (error) {
        [SVProgressHUD showInfoWithStatus:@"摄像头不可用"];
        return;
    }
    
    if ([self.device lockForConfiguration:nil])
    {
        //自动白平衡
        if ([self.device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance])
        {
            [self.device setWhiteBalanceMode:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance];
        }
        //自动对焦
        if ([self.device isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus])
        {
            [self.device setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
        }
        //自动曝光
        if ([self.device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure])
        {
            [self.device setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
        }
        [self.device unlockForConfiguration];
    }
    
    //生成输出对象
    self.output = [[AVCaptureMetadataOutput alloc]init];
    
    //设置代理，一旦扫描到指定类型的数据，就会通过代理输出
    //在扫描的过程中，会分析扫描的内容，分析成功后就会调用代理方法在队列中输出
    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    //生成会话，用来结合输入输出
    self.session = [[AVCaptureSession alloc]init];
    if ([self.session canAddInput:self.input]) {
        [self.session addInput:self.input];
    }
    if ([self.session canAddOutput:self.output]) {
        [self.session addOutput:self.output];
    }
    
    //指定当扫描到二维码的时候，产生输出
    //AVMetadataObjectTypeQRCode 指定二维码
    //指定识别类型一定要放到添加到session之后
    /*
     AVMetadataObjectTypeEAN13Code,
     AVMetadataObjectTypeEAN8Code,
     AVMetadataObjectTypeCode128Code,
     AVMetadataObjectTypeQRCode
     */
    
    NSMutableArray *array = [[NSMutableArray alloc] init];
    if ([self.output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
        [array addObject:AVMetadataObjectTypeQRCode];
    }
    if ([self.output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) {
        [array addObject:AVMetadataObjectTypeEAN13Code];
    }
    if ([self.output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) {
        [array addObject:AVMetadataObjectTypeEAN8Code];
    }
    if ([self.output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {
        [array addObject:AVMetadataObjectTypeCode128Code];
    }
    [self.output setMetadataObjectTypes:array];
    
#warning - 下一行代码 ios8 会崩溃
    // 设置信息采集质量
//    if ([self.session canSetSessionPreset:AVCaptureSessionPreset3840x2160]) {
//        self.session.sessionPreset = AVCaptureSessionPreset3840x2160;//4k
//    }else if ([self.session canSetSessionPreset:AVCaptureSessionPreset1920x1080]){
//        self.session.sessionPreset = AVCaptureSessionPreset1920x1080;//1080P
//    }else if ([self.session canSetSessionPreset:AVCaptureSessionPreset1280x720]){
//        self.session.sessionPreset = AVCaptureSessionPreset1280x720;//1080P
//    }else if ([self.session canSetSessionPreset:AVCaptureSessionPresetHigh]){
//        self.session.sessionPreset = AVCaptureSessionPresetHigh;//High
//    }else{
//        self.session.sessionPreset = AVCaptureSessionPresetHigh;
//    }
    /*设置扫描信息的识别区域
     
    Y<--------------------------+ (0,0)
    (0,1)                       |
                                |
                                |
                                |
                 屏幕            |
                                |
                                |
                                |
                                |
                                |
    (1,1)                       | X (1,0)
     
     
     */
    
    // 1.获取屏幕的frame
    CGRect viewRect = self.view.frame;
    // 2.获取扫描容器的frame
    CGRect containerRect = self.rectScanZone;
    
    CGFloat x = containerRect.origin.y / viewRect.size.height;
    CGFloat y = containerRect.origin.x / viewRect.size.width;
    CGFloat width = containerRect.size.height / viewRect.size.height;
    CGFloat height = containerRect.size.width / viewRect.size.width;
    
    [self.output setRectOfInterest:CGRectMake(x ,y , width, height)];
    
    
    //使用self.session，初始化预览层，self.session负责驱动input进行信息的采集，layer负责把图像渲染显示
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.previewLayer.frame = self.view.bounds;
    [self.view.layer addSublayer:self.previewLayer];
    
    
    [self.view addSubview:self.viewMask];
    [self imageScanZone];
    [self.view addSubview:self.imageMove];
    [self buttonAlbum];
    [self buttonTurn];
    [self buttonQRCode];
    [self labelAlert];
    
    
    
    // 3.如果不支持闪光灯，不显示闪光灯按钮
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    self.buttonTurn.hidden = !device.hasTorch;
    
    //开始启动
    [self.session startRunning];
}


#pragma mark 输出的代理
//metadataObjects ：把识别到的内容放到该数组中
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    [self playSystemSound];
    NSString *stringValue;
    if ([metadataObjects count] > 0) {
        //停止扫描
        [_session stopRunning];
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
        stringValue = metadataObject.stringValue;
        [self stopAnimation];// 停止动画
        
        
        if ([self.delegate respondsToSelector:@selector(qrCodeScanSuccessWithResult:)]) {
            [self.delegate qrCodeScanSuccessWithResult:stringValue];
        }
        
        [self.navigationController popViewControllerAnimated:NO];
    }
}

- (UIImageView *)imageScanZone {
    if (!_imageScanZone) {
        _imageScanZone = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"st_scanBackground"]];
        [self.view addSubview:_imageScanZone];
        [_imageScanZone mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.mas_equalTo(Main_Width*0.25);
            make.top.mas_equalTo(Main_Height*0.2);
            make.size.mas_equalTo(CGSizeMake(Main_Width*0.5, Main_Width*0.5));
        }];
    }
    return _imageScanZone;
}

- (UIView *)viewMask {
    if (!_viewMask) {
        _viewMask = [[UIView alloc] initWithFrame:self.view.bounds];
        [_viewMask setBackgroundColor:[UIColor blackColor]];
        [_viewMask setAlpha:102.0/255];
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path appendPath:[UIBezierPath bezierPathWithRect:_viewMask.bounds]];
        [path appendPath:[UIBezierPath bezierPathWithRect:self.rectScanZone].bezierPathByReversingPath];
        CAShapeLayer *maskLayer = [CAShapeLayer layer];
        maskLayer.path = path.CGPath;
        _viewMask.layer.mask = maskLayer;
    }
    return _viewMask;
}

- (UIImageView *)imageMove {
    if (!_imageMove) {
        CGFloat viewW = Main_Width*0.5;
        CGFloat viewH = 3;
        CGFloat viewX = (Main_Width - viewW)/2;
        CGFloat viewY = Main_Height*0.2;
        _imageMove = [[UIImageView alloc]initWithFrame:CGRectMake(viewX, viewY, viewW, viewH)];
        _imageMove.image = [UIImage imageNamed:@"qrcode_scan_light_green"];

    }
    return _imageMove;
}


- (UIButton *)buttonAlbum {
    if (!_buttonAlbum) {
        _buttonAlbum = [UIButton buttonWithType:UIButtonTypeCustom];
        [_buttonAlbum setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_photo_nor"] forState:UIControlStateNormal];
        [_buttonAlbum setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_photo_down"] forState:UIControlStateSelected];
        [_buttonAlbum setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_photo_down"] forState:UIControlStateHighlighted];
        [_buttonAlbum sizeToFit];
        [_buttonAlbum addTarget:self action:@selector(albumTorchEvent:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_buttonAlbum];
        [_buttonAlbum mas_makeConstraints:^(MASConstraintMaker *make) {
            make.size.mas_equalTo(CGSizeMake(65*Scale_W, 90*Scale_W));
            make.bottom.mas_equalTo(self.view).offset(-50*Scale_W);
            make.centerX.mas_equalTo(_imageScanZone.mas_left).offset(-20*Scale_W);
        }];
    }
    return _buttonAlbum;
}

#pragma mark - albumTorchEvent
- (void)albumTorchEvent:(UIButton *)sender {
    [self alumbEvent];
}

- (UIButton *)buttonTurn {
    if (!_buttonTurn) {
        _buttonTurn = [UIButton buttonWithType:UIButtonTypeCustom];
        _buttonTurn.isIgnore = YES;// 忽略重复点击屏蔽
        [_buttonTurn setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_flash_nor"] forState:UIControlStateNormal];
        [_buttonTurn setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_flash_down"] forState:UIControlStateSelected];
        [_buttonTurn setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_flash_down"] forState:UIControlStateHighlighted];
        [_buttonTurn sizeToFit];
        [_buttonTurn addTarget:self action:@selector(turnTorchEvent:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_buttonTurn];
        [_buttonTurn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.size.mas_equalTo(CGSizeMake(65*Scale_W, 90*Scale_W));
            make.bottom.mas_equalTo(self.view).offset(-50*Scale_W);
            make.centerX.mas_equalTo(_imageScanZone);
        }];
    }
    return _buttonTurn;
}

- (void)turnTorchEvent:(UIButton *)button {
    
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if ([device hasTorch] && [device hasFlash]){
        [device lockForConfiguration:nil];
        if (!button.selected) {
            [device setTorchMode:AVCaptureTorchModeOn];
            [device setFlashMode:AVCaptureFlashModeOn];
            button.selected = YES;
        } else {
            [device setTorchMode:AVCaptureTorchModeOff];
            [device setFlashMode:AVCaptureFlashModeOff];
            button.selected = NO;
        }
        [device unlockForConfiguration];
    }
}


- (UIButton *)buttonQRCode {
    if (!_buttonQRCode) {
        _buttonQRCode = [UIButton buttonWithType:UIButtonTypeCustom];
        [_buttonQRCode setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_myqrcode_nor"] forState:UIControlStateNormal];
        [_buttonQRCode setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_myqrcode_down"] forState:UIControlStateSelected];
        [_buttonQRCode setBackgroundImage:[UIImage imageNamed:@"qrcode_scan_btn_myqrcode_down"] forState:UIControlStateHighlighted];
        [_buttonQRCode sizeToFit];
        [_buttonQRCode addTarget:self action:@selector(qrcodeTorchEvent:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_buttonQRCode];
        [_buttonQRCode mas_makeConstraints:^(MASConstraintMaker *make) {
            make.size.mas_equalTo(CGSizeMake(65*Scale_W, 90*Scale_W));
            make.bottom.mas_equalTo(self.view).offset(-50*Scale_W);
            make.centerX.mas_equalTo(_imageScanZone.mas_right).offset(20*Scale_W);
        }];
    }
    return _buttonQRCode;
}





- (void)qrcodeTorchEvent:(UIButton *)sender {
    XKQRCoderController *myQRCodeVC = [[XKQRCoderController alloc] init];
    myQRCodeVC.qr_base_url = _qr_url;
    [self.navigationController pushViewController:myQRCodeVC animated:YES];
}

- (UILabel *)labelAlert {
    if (!_labelAlert) {
        _labelAlert = [[UILabel alloc] init];
        _labelAlert.numberOfLines = 0;
        [_labelAlert setText:@"将二维码放置框内\n即可开始扫描"];
        [_labelAlert setTextColor:[UIColor whiteColor]];
        [_labelAlert setFont:[UIFont systemFontOfSize:17]];
        [_labelAlert setTextAlignment:NSTextAlignmentCenter];
        
        [self.view addSubview:_labelAlert];
        [_labelAlert mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.mas_equalTo(self.view);
            make.bottom.mas_equalTo(_imageScanZone.mas_top).offset(-20*Scale_W);
        }];
    }
    return _labelAlert;
}

- (CGRect)rectScanZone {
    return CGRectMake(Main_Width*0.25, Main_Height*0.2, Main_Width*0.5, Main_Width*0.5);
}

- (void)startAnimation {

    [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionRepeat animations:^{
        self.imageMove.transform = CGAffineTransformTranslate(self.imageMove.transform, 0, Main_Width*0.5-3);
    } completion:^(BOOL finished) {
        self.imageMove.transform = CGAffineTransformIdentity;
    }];
}

- (void)stopAnimation {
    [UIView animateWithDuration:0.01 animations:^{
        self.imageMove.transform = CGAffineTransformIdentity;
    }];
}

// 4.播放提示音
- (void)playSystemSound {
    
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
    
//    SystemSoundID soundID;
//    NSString *strSoundFile = [[NSBundle mainBundle] pathForResource:@"st_noticeMusic" ofType:@"wav"];
//    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:strSoundFile],&soundID);
//    AudioServicesPlaySystemSound(soundID);
}



- (void)authorizationStatus{
    NSString *mediaType = AVMediaTypeVideo;
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    if (authStatus == AVAuthorizationStatusAuthorized) {
        [self.session startRunning];
        [self startAnimation];
    }else {
        [SVProgressHUD showInfoWithStatus:@"请在设置中开启摄像头权限"];
        [self.session stopRunning];
        [self stopAnimation];
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(observeAuthrizationStatusChange) userInfo:nil repeats:YES];
    }
}

// 1.监听摄像头权限
- (void)observeAuthrizationStatusChange{
    NSString *mediaType = AVMediaTypeVideo;
    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
    if (authStatus == AVAuthorizationStatusAuthorized) {
        [self.timer invalidate];
        self.timer = nil;
        [self.session startRunning];
        [self startAnimation];
    }
}


- (CIDetector *)detector {
    if (!_detector) {
        _detector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:@{ CIDetectorAccuracy : CIDetectorAccuracyHigh }];
    }
    return _detector;
}


- (void)setQr_url:(NSString *)qr_url {
    _qr_url = qr_url;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
}

@end
